﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using TuanJuAPIManager.DealProviders;

namespace TuanJuAPIManager
{
    public class TuanApi
    {
        private string city = string.Empty;
        private List<Deal> deals = new List<Deal>();
        private List<Deal> recommendDeals = new List<Deal>();
        private Dictionary<string, List<Deal>> recommends = new Dictionary<string, List<Deal>>();
        private Dictionary<string, IEnumerable<Deal>> dictionaryDeals = new Dictionary<string, IEnumerable<Deal>>();
        private Settings setting = new Settings();
        private Dictionary<string, string> website = new Dictionary<string, string>();

        private static Dictionary<string, TuanApi> cities = new Dictionary<string, TuanApi>();

        private TuanApi(string cityName)
        {
            this.city = cityName;
        }

        public static TuanApi GetInstance(string cityName)
        {
            if (!cities.ContainsKey(cityName))
            {
                cities.Add(cityName, new TuanApi(cityName));
            }

            return cities[cityName];
        }

        ///// <summary>
        ///// initialize the TuanAPI
        ///// </summary>
        ///// <param name="cityName">which city</param>
        //public TuanApi(string cityName)
        //{
        //    this.city = cityName;
        //}

        /// <summary>
        /// Get the one deal data by dealId
        /// </summary>
        /// <param name="dealId">deal id</param>
        /// <returns>One row data</returns>
        public async Task<Deal> GetDeal(string dealId)
        {
            if (deals.Count <= 0)
            {
                deals = await GetDeals();
            }

            return deals.Where(d => d.Gid == dealId).FirstOrDefault();
        }

        /// <summary>
        /// Get all deal data
        /// </summary>
        /// <returns>all deal data</returns>
        public async Task<List<Deal>> GetDeals()
        {
            Dictionary<string, string> website = await GetWebsite();

            foreach (string provider in website.Keys)
            {
                IDealProvider dealProvider = GetProvider(provider);

                IEnumerable<Deal> iDeal = await dealProvider.GetDeals(this.city);

                ////Add data to dictionary deals for recommend data
                dictionaryDeals.Add(provider, iDeal);

                foreach (Deal deal in iDeal)
                {
                    deals.Add(deal);
                }
            }

            return deals;
        }

        /// <summary>
        /// Get the one category data
        /// </summary>
        /// <param name="category">which category</param>
        /// <returns>one category data</returns>
        public async Task<List<Deal>> GetDeals(Category category)
        {
            if (deals.Count <= 0)
            {
                deals = await GetDeals();
            }

            return deals.Where(d => d.Category == category).ToList();
        }

        /// <summary>
        /// Get the website recommend data
        /// </summary>
        /// <param name="dealCount">how many deal count need to get</param>
        /// <returns>the website recommend data</returns>
        public async Task<List<Deal>> GetRecommends(int dealCount)
        {
            if (recommends.ContainsKey(this.city))
            {
                var deals = recommends[this.city];

                if (deals == null || deals.Count == 0)
                {
                    recommends[this.city] = await GetTotalRecommends(dealCount);
                }
            }
            else
            {
                recommends.Add(this.city, await GetTotalRecommends(dealCount));
            }


            return recommends[this.city];
        }

        private async Task<List<Deal>> GetTotalRecommends(int dealCount)
        {
            Dictionary<string, string> website = await GetWebsite();

            int websiteCount = website.Keys.Count;
            var count = dealCount / websiteCount + 1;

            List<Deal> deals = new List<Deal>();

            foreach (string provider in website.Keys)
            {
                IEnumerable<Deal> providerDeals = dictionaryDeals[provider].Take(count);

                foreach (Deal deal in providerDeals)
                {
                    deals.Add(deal);
                }
            }

            return deals;
        }

        /// <summary>
        /// Get all citys
        /// </summary>
        /// <returns>all city list</returns>
        public async Task<IEnumerable<City>> GetCities()
        {
            var cities = await DataManager.GetCityAsync();
            return cities.Values;
        }

        private async Task<Dictionary<string, string>> GetWebsite()
        {
            if (website.Count <= 0)
            {
                website = await DataManager.GetWebsiteAsync();
            }

            return website;
        }

        /// <summary>
        /// Get the provider
        /// </summary>
        /// <param name="provider">which website provider</param>
        /// <returns>provider class</returns>
        private IDealProvider GetProvider(string provider)
        {
            IDealProvider dealProvider = null;
            switch (provider.ToLower())
            {
                case "lashou":
                    dealProvider = new Lashou();
                    break;
                case "meiTuan":
                    dealProvider = new MeiTuan();
                    break;
                case "dianping":
                    dealProvider = new Dianping();
                    break;
                default:
                    break;
            }

            return dealProvider;
        }
    }
}